#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "framework.h"
#include "buildsettings.h"
void Help(void);
void TestTreeOperations(void);
void TestTreeExtensions(void);
void TestForestOperations(void);

/*
*
* Write more tests!
*
* Grow your life! Grow the world!!!
*
*/

//! Defines a single mapping from a string to a function.
typedef struct LCaseMapping
{
	//! A string (used as key)
	char *String;
	//! A function pointer (used as value)
	void (*Function)(void);
} CaseMapping;

//! Defines a set of strings mapped to functions.
CaseMapping Mapping[] =
{
	{"help", Help},
	{"tree-operations", TestTreeOperations},
	{"tree-extensions", TestTreeExtensions},
	{"forest-operations", TestForestOperations}
};

/*!
  Tester entry point.
*/
int main(int argc, char *argv[])
{
	int i=0;
	int numMappings;
	void (*func)(void) = 0x0;

	// Check argument count
	if (argc <= 1)
	{
		printf("Enter a test case as an argument.\n\n");
		return 0;
	}
	
	// Calculate number of mappings
	numMappings = sizeof(Mapping)/sizeof(struct LCaseMapping);
	
	// Search through array for the key
	// Time: O(|Mapping|)
	while (i < numMappings)
	{
		if (strcmp(argv[1], Mapping[i].String) == 0)
			func = Mapping[i].Function;
		i=i+1;
	}
	// If found, call mapped function
	if (func != 0x0)
		func();
	return 0;
}

// Test Cases Follow:

/*!
  Print the array of mappings.
  This function should be in every tester
*/
void Help(void)
{
	int i=0;
	int numMappings = sizeof(Mapping)/sizeof(struct LCaseMapping);

	printf("Mappings:\n");
	while (i < numMappings)
	{
		printf("  >%s\n", Mapping[i].String);
		i=i+1;
	}
}

/*!
  Test every operation on the tree.
  Set VERBOSE flag to true to follow the operations.
*/
void TestTreeOperations(void)
{
	Tree t = CreateTree();
	printf("Creating root...\n");
	t.Root = CreateTreeNode();
	printf("Creating child...\n");
	InsertTreeChild(t.Root, CreateTreeNode());
	printf("Creating child...\n");
	InsertTreeChild(t.Root, CreateTreeNode());
	printf("In Order Print...\n");
	PrintTree(t);
	printf("Destroying tree..\n");
	printf("%d nodes destroyed.\n", FreeTreeNode(t.Root));
	printf("Done.\n");
	t.Root = 0x0;
}

/*!
* Test the data extension field in the tree nodes.
* Set VERBOSE to true to follow the operations.
*/
void TestTreeExtensions(void)
{
	Task *v;
	TreeNode *node;

	printf("Creating tree.\n");
	Tree t = CreateTree();
	printf("Creating root tree node.\n");
	t.Root = CreateTreeNode();

	printf("Creating task.\n");
	v = (Task*)malloc(sizeof(struct LTask));
	strcpy(v->Name, "Feed the dog");
	strcpy(v->Description, "Duh.");
	printf("Creating tree node.\n");
	node = CreateTreeNode();
	node->Value = v;
	node->ValueType = TREENODEVALUETYPE_TASK;
	InsertTreeChild(t.Root, node);

	printf("Printing tree.\n");
	PrintTree(t);

	printf("Destroying tree.\n");
	FreeTreeNode(t.Root);
}

void TestForestOperations(void)
{
	printf("Creating forest A.\n");
	Forest A = CreateForest();
	printf("Populating forest A\n");
	A = FoAppendRoot(A, CreateTreeNode());
	A = FoAppendRoot(A, CreateTreeNode());
	printf("Creating forest B.\n");
	Forest B = CreateForest();
	printf("Populating forest B\n");
	B = FoAppendRoot(B, CreateTreeNode());
	B = FoAppendRoot(B, CreateTreeNode());

	printf("A:\n");
	PrintForest(A);
	printf("\nB:\n");
	PrintForest(B);

	printf("\n\nMerging forests.\n\n");
	Forest C = FoMerge(A,B);
	printf("A:\n");
	PrintForest(A);
	printf("B:\n");
	PrintForest(B);
	printf("C:\n");
	PrintForest(C);

}
